use std::io::{self, Write};

pub struct Logger(pub Box<dyn Write>);

pub fn stderr() -> Logger {
    Logger(Box::new(io::stderr()))
}

#[macro_export]
macro_rules! log {
    ($l:expr) => (
        $l.as_ref().map(|l| l.borrow_mut().0.write("\n".as_bytes()).is_ok())
    );
    ($l:expr, $fmt:expr) => (
        $l.as_ref().map(|l| l.borrow_mut().0.write(concat!($fmt, "\n").as_bytes()).is_ok())
    );
    ($l:expr, $fmt:expr, $($arg:tt)*) => (
        $l.as_ref().map(
            |l| l.borrow_mut().0.write_fmt(format_args!(concat!($fmt, "\n"), $($arg)*)).is_ok()
        )
    );
}

#[cfg(test)]
mod tests {
    use std::cell::RefCell;
    use std::io::BufWriter;
    use super::*;

    // 创建测试用的日志写入器
    fn create_test_logger() -> Option<RefCell<(BufWriter<Vec<u8>>, ())>> {
        Some(RefCell::new((BufWriter::new(Vec::new()), ())))
    }

    // 从日志写入器中获取内容
    fn get_log_content(logger: &Option<RefCell<(BufWriter<Vec<u8>>, ())>>) -> String {
        let mut cell = logger.as_ref().unwrap().borrow_mut();
        // 确保所有内容都被刷新到缓冲区
        cell.0.flush().unwrap();
        String::from_utf8(cell.0.get_mut().clone()).unwrap()
    }

    #[test]
    fn test_log_empty() {
        let logger = create_test_logger();
        // 测试无格式参数的情况
        log!(logger);
        assert_eq!(get_log_content(&logger), "\n");
    }

    #[test]
    fn test_log_static_string() {
        let logger = create_test_logger();
        // 测试静态字符串格式
        log!(logger, "hello world");
        assert_eq!(get_log_content(&logger), "hello world\n");
    }

    #[test]
    fn test_log_with_args() {
        let logger = create_test_logger();
        // 测试带参数的格式化
        log!(logger, "number: {}, string: {}", 42, "test");
        assert_eq!(get_log_content(&logger), "number: 42, string: test\n");
    }

    #[test]
    fn test_log_multiple_calls() {
        let logger = create_test_logger();
        // 测试多次调用
        log!(logger, "first line");
        log!(logger, "second line with number: {}", 100);
        log!(logger);

        assert_eq!(
            get_log_content(&logger),
            "first line\nsecond line with number: 100\n\n"
        );
    }

    #[test]
    fn test_log_none_logger() {
        // 测试当 logger 为 None 时不会 panic
        let logger: Option<RefCell<(BufWriter<Vec<u8>>, ())>> = None;
        log!(logger, "this should do nothing");
        // 没有断言，只要不崩溃就是通过
    }
}